/*
 * atk_lora_01.c
 *
 *  Created on: 2022年2月1日
 *      Author: TamGitsun
 */


#include "atk_lora_01.h"
#include "tos_at.h"
#include "lora_module_wrapper.h"
#include "fsl_debug_console.h"
#include <stdio.h>


#define DELAY(ms) tos_task_delay(ms)


static int atk_lora_init(void)
{
	return 0;
}


int atk_lora_send(const char *buf, size_t len, char * expected, char * recv_buf, size_t recv_buf_size)
{
    int try = 0;
	at_echo_t echo;

	char cmd[128] = {0};

    if (len > sizeof(cmd) - 2) {
        return -1;
    }

    memcpy(cmd, buf, sizeof(cmd) > len ? len : sizeof(cmd));
    memcpy(cmd + len, "\r\n", 2);

	tos_at_echo_create(&echo, NULL, 0, expected);
	while (try++ < 10) {
		tos_at_cmd_exec(&echo, 3000, cmd);
		if (echo.status == AT_ECHO_STATUS_OK || echo.status == AT_ECHO_STATUS_EXPECT) {
            PRINTF("%s %d\r\n", __FUNCTION__, __LINE__);
			return 0;
		}
	}
	return -1;
}


static int atk_lora_close(void)
{
	return 0;
}


static lora_module_t lora_module_atk_lora = {
    .init             = atk_lora_init,
    .join_otaa        = K_NULL,
    .join_abp         = K_NULL,
    .send             = K_NULL,
    .send_unconfirmed = K_NULL,
    .close            = atk_lora_close,
    .recv_callback    = K_NULL,
};


static at_event_t * atk_lora_at_event = K_NULL;
static atk_lora_recv_event_t * atk_lora_recv_events = K_NULL;


static void atk_lora_at_event_callback(atk_lora_recv_event_t * event_handler,
    char * incoming_data_buffer, uint32_t size)
{
    int offset = 0;
    int err = 0;
    int is_recv_finish = 0;
    uint8_t data;

    memset(incoming_data_buffer, 0x00, size);

    k_tick_t begin = tos_systick_get();

    while ((tos_systick_get() - begin) < event_handler->timeout
    		&& 0 == is_recv_finish
			&& 0 == err)
    {
        tos_at_uart_read(&data, 1);
        switch (data)
        {
        case '\r':
        	continue;
        case '\n':
        	is_recv_finish = 1;
        	break;
        default:
			if (offset < size)
			{
				incoming_data_buffer[offset++] = data;
				continue;
			}
			printf(" ERR:incomming data is big ,please give more space for incoming_data_buffer\n");
			err = -1;
			break;
        }
    }

    // printf("[%p] Received err: %d finished: %d prefix: %s data: %s\n",
    // 		event_handler, err, is_recv_finish, event_handler->event, incoming_data_buffer);

    if (0 != is_recv_finish && event_handler->handler)
    {
    	event_handler->handler(event_handler->event, incoming_data_buffer, offset);
    }
}


static void atk_lora_at_event_callback_0(void)
{
    static char incoming_data_buffer[128];
	atk_lora_at_event_callback(&(atk_lora_recv_events[0]), incoming_data_buffer, sizeof(incoming_data_buffer));
}


static void atk_lora_at_event_callback_1(void)
{
    static char incoming_data_buffer[128];
	atk_lora_at_event_callback(&(atk_lora_recv_events[1]), incoming_data_buffer, sizeof(incoming_data_buffer));
}


static void atk_lora_at_event_callback_2(void)
{
    static char incoming_data_buffer[128];
	atk_lora_at_event_callback(&(atk_lora_recv_events[2]), incoming_data_buffer, sizeof(incoming_data_buffer));
}


static void atk_lora_at_event_callback_3(void)
{
    static char incoming_data_buffer[128];
	atk_lora_at_event_callback(&(atk_lora_recv_events[3]), incoming_data_buffer, sizeof(incoming_data_buffer));
}


static void atk_lora_at_event_callback_4(void)
{
    static char incoming_data_buffer[128];
	atk_lora_at_event_callback(&(atk_lora_recv_events[4]), incoming_data_buffer, sizeof(incoming_data_buffer));
}


static at_event_callback_t event_callback_list[] = {
		atk_lora_at_event_callback_0,
		atk_lora_at_event_callback_1,
		atk_lora_at_event_callback_2,
		atk_lora_at_event_callback_3,
		atk_lora_at_event_callback_4,
};


int atk_lora_lora_init(hal_uart_port_t uart_port, atk_lora_recv_event_t * events, size_t n_events)
{
	atk_lora_at_event = tos_mmheap_alloc(sizeof(at_event_t) * n_events);
	if (K_NULL == atk_lora_at_event)
	{
		return -1;
	}
	atk_lora_recv_events = tos_mmheap_alloc(sizeof(atk_lora_recv_event_t) * n_events);
	if (K_NULL == atk_lora_recv_events)
	{
		return -1;
	}
	for (size_t i = 0; i < n_events && i < (sizeof(event_callback_list) / sizeof(at_event_callback_t)); ++i)
	{
		atk_lora_at_event[i].event_header = events[i].event;
		atk_lora_at_event[i].event_callback = event_callback_list[i];
		atk_lora_recv_events[i].event = events[i].event;
		atk_lora_recv_events[i].handler = events[i].handler;
		atk_lora_recv_events[i].timeout = events[i].timeout;
		printf("event handler: %p\n", &(atk_lora_recv_events[i]));
	}

    if (tos_at_init(uart_port, atk_lora_at_event, n_events) != 0) {
        return -1;
    }

    DELAY(1000);

    if (tos_lora_module_register(&lora_module_atk_lora) != 0) {
        return -1;
    }

    if (tos_lora_module_init() != 0) {
        return -1;
    }

    return 0;
}
